package org.vudroid.core;

import android.app.Dialog;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.*;
import android.widget.*;
import org.vudroid.R;
import org.vudroid.core.events.CurrentPageListener;
import org.vudroid.core.events.DecodingProgressListener;
import org.vudroid.core.events.ExitListener;
import org.vudroid.core.ex3ndr.NookBaseActivity;
import org.vudroid.core.models.*;
import org.vudroid.ui.menu.MenuPanel;

import java.util.HashMap;
import java.util.Map;

public abstract class BaseViewerActivity extends NookBaseActivity implements DecodingProgressListener, CurrentPageListener, ExitListener
{
    private static final int MENU_EXIT = 0;
    private static final int MENU_GOTO = 1;
    private static final int MENU_FULL_SCREEN = 2;
    private static final int DIALOG_GOTO = 0;
    private static final String DOCUMENT_VIEW_STATE_PREFERENCES = "DjvuDocumentViewState";
    private DecodeService decodeService;
    private DocumentView documentView;
    private ViewGroup toolBarView;
    private ViewerPreferences viewerPreferences;
//    private Toast pageNumberToast;

    /**
     * Called when the activity is first created.
     */
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        initDecodeService();
        final ZoomModel zoomModel = new ZoomModel();
        final ShiftModel shiftModel = new ShiftModel();
        final DecodingProgressModel progressModel = new DecodingProgressModel();
        progressModel.addEventListener(this);
        final CurrentPageModel currentPageModel = new CurrentPageModel();
        currentPageModel.addEventListener(this);
        final ExitModel exitModel = new ExitModel();
        exitModel.addEventListener(this);
        documentView = new DocumentView(this, zoomModel, progressModel, currentPageModel);
        documentView.setClickable(false);
        documentView.setFocusable(false);
        documentView.setFocusableInTouchMode(false);
        zoomModel.addEventListener(documentView);
        shiftModel.addEventListener(documentView);
        documentView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT));
        decodeService.setContentResolver(getContentResolver());
        decodeService.setContainerView(documentView);
        documentView.setDecodeService(decodeService);
        decodeService.open(getIntent().getData());

        viewerPreferences = new ViewerPreferences(this);

        setContentView(R.layout.nook);
        findViewById(R.id.einkScreen).setClickable(false);
        ((FrameLayout) findViewById(R.id.einkScreen)).addView(documentView);

        final SharedPreferences sharedPreferences = getSharedPreferences(DOCUMENT_VIEW_STATE_PREFERENCES, 0);
        documentView.goToPage(sharedPreferences.getInt(getIntent().getData().toString(), 0));
        documentView.showDocument();

        viewerPreferences.addRecent(getIntent().getData());

//        createListeners();

        toolBarView = (LinearLayout) findViewById(R.id.lcdScreen);
        toolBarView.removeAllViews();
        MenuPanel menuPanel = new MenuPanel(this, decodeService, documentView, zoomModel, toolBarView, exitModel, shiftModel);
    }

    private void createListeners()
    {
        ((Button) findViewById(R.id.goToButton)).setOnClickListener(new View.OnClickListener()
        {
            public void onClick(View view)
            {
                final TextView text = (TextView) findViewById(R.id.pageNumberTextEdit);
                final int pageNumber = Integer.parseInt(text.getText().toString());
                if (pageNumber < 1 || pageNumber > decodeService.getPageCount())
                {
                    Toast.makeText(getApplicationContext(), "Page number out of range. Valid range: 1-" + decodeService.getPageCount(), 2000).show();
                    return;
                }
                documentView.goToPage(pageNumber - 1);
            }
        });
    }

    @Override
    public Object onRetainNonConfigurationInstance()
    {
        Map<String, Object> cache = new HashMap<String, Object>();

        Map<Integer, ?> pages = documentView.getPages();
        cache.put("pages", pages);

        cache.put("decodeService", decodeService);

        return cache;
    }

    public void decodingProgressChanged(final int currentlyDecoding)
    {
        runOnUiThread(new Runnable()
        {
            public void run()
            {
                getWindow().setFeatureInt(Window.FEATURE_INDETERMINATE_PROGRESS, currentlyDecoding == 0 ? 10000 : currentlyDecoding);
            }
        });
    }

    public void currentPageChanged(int pageIndex)
    {
//        final String pageText = (pageIndex + 1) + "/" + decodeService.getPageCount();
//        if (pageNumberToast != null) {
//            pageNumberToast.setText(pageText);
//        } else {
//            pageNumberToast = Toast.makeText(this, pageText, 300);
//        }
//        pageNumberToast.setGravity(Gravity.TOP | Gravity.LEFT, 0, 0);
//        pageNumberToast.show();
    }

    private void setWindowTitle()
    {
        final String name = getIntent().getData().getLastPathSegment();
        getWindow().setTitle(name);
    }

    @Override
    protected void onPostCreate(Bundle savedInstanceState)
    {
        super.onPostCreate(savedInstanceState);
        setWindowTitle();
    }

    private void initDecodeService()
    {
        if (decodeService == null)
        {
            decodeService = createDecodeService();
        }
    }

    protected abstract DecodeService createDecodeService();

    @Override
    protected void onStop()
    {
        super.onStop();
        saveCurrentPage();
    }

    public void saveCurrentPage()
    {
        final SharedPreferences sharedPreferences = getSharedPreferences(DOCUMENT_VIEW_STATE_PREFERENCES, 0);
        final SharedPreferences.Editor editor = sharedPreferences.edit();
        editor.putInt(getIntent().getData().toString(), documentView.getCurrentPage());
        editor.commit();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu)
    {
        menu.add(0, MENU_EXIT, 0, "Exit");
        menu.add(0, MENU_GOTO, 0, "Go to page");
        final MenuItem menuItem = menu.add(0, MENU_FULL_SCREEN, 0, "Full screen").setCheckable(true).setChecked(viewerPreferences.isFullScreen());
        setFullScreenMenuItemText(menuItem);
        return true;
    }

    private void setFullScreenMenuItemText(MenuItem menuItem)
    {
        menuItem.setTitle("Full screen " + (menuItem.isChecked() ? "on" : "off"));
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item)
    {
        switch (item.getItemId())
        {
            case MENU_EXIT:
                saveCurrentPage();
                System.exit(0);
                return true;
            case MENU_GOTO:
                showDialog(DIALOG_GOTO);
                return true;
            case MENU_FULL_SCREEN:
                item.setChecked(!item.isChecked());
                setFullScreenMenuItemText(item);
                viewerPreferences.setFullScreen(item.isChecked());

                finish();
                startActivity(getIntent());
                return true;
        }
        return false;
    }

    @Override
    protected Dialog onCreateDialog(int id)
    {
        switch (id)
        {
            case DIALOG_GOTO:
                return new GoToPageDialog(this, documentView, decodeService);
        }
        return null;
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event)
    {
        boolean handled = false;
        switch (keyCode)
        {
            case NOOK_PAGE_UP_KEY_LEFT:
            case NOOK_PAGE_UP_KEY_RIGHT:
            case NOOK_PAGE_UP_SWIPE:
                documentView.scrollPrevRect();
                handled = true;
                break;

            case NOOK_PAGE_DOWN_KEY_LEFT:
            case NOOK_PAGE_DOWN_KEY_RIGHT:
            case NOOK_PAGE_DOWN_SWIPE:
                documentView.scrollNextRect();
                handled = true;
                break;

            default:
                break;
        }
        return handled;
    }

    public void exit()
    {
        saveCurrentPage();
        System.exit(0);
    }
}
